﻿// 角色高光计算
Shader "Demon/Demon_matcap/Matcap_1"
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}

		// 高光 (角色高光)
		[Header(Specular)]
		[Toggle]_SPECULAR("_SPECULAR_ON",int) = 1
		_SpecularColor("SpecularColor",Color) = (1,1,1,1) //高光颜色
		_Gloss("Gloss",Range(0,1)) = 0.5 // 高光范围
		_SpecularIntensity("SpecularIntensity",Range(0,2)) = 1 // 高光强度

		// 高光（matcap 贴图计算的高光） 
		[Header(Reflect)]
		[Toggle]_REFLECT("_REFLECT_ON",int) = 1
		_MatCap("MatCap",2D) = "white" {}				//圆形的 MatCap 贴图纹理
		_SpecularAO("SpecularAO",Range(0,1)) = 0.1     // 强度
	}
	SubShader
	{
		Tags { "RenderType"="Opaque" }

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			// make fog work
			#pragma multi_compile_fog
			// specular
			#pragma multi_compile _ _SPECULAR_ON
			// matcap
			#pragma multi_compile _ _REFLECT_ON
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
				float3 normal : NORMAL;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				UNITY_FOG_COORDS(1)
				float4 vertex : SV_POSITION;
				float4 posWorld : TEXCOORD2;
				float3 normalDir : TEXCOORD3;
				// matcap 高光 反射
				#if _REFLECT_ON
					float2 matcap : TEXCOORD4;
				#endif
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;

			
			// 高光（角色）
			#if _SPECUlAR_ON
				uniform float4 _SpecularColor;
				uniform float _Gloss;
			#endif

			// 高光 (matcap)
			#if _REFLECT_ON
				uniform sampler2D _MatCap;
				uniform float _SpecularAO;
			#endif

			uniform float _SpecularIntensity;
			
			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);  //v.uv; 
				o.posWorld = mul(unity_ObjectToWorld,v.vertex);
				o.normalDir.xyz = UnityObjectToWorldNormal(v.normal.xyz);
				UNITY_TRANSFER_FOG(o,o.vertex);
				// 从结果来看 mul更加节约计算量
				#if _REFLECT_ON
					float3 worldNormal = normalize(mul((float3x3)unity_WorldToObject,v.normal.xyz));
					//float3 worldNormal = normalize(unity_WorldToObject[0].xyz * v.normal.x + unity_WorldToObject[1].xyz * v.normal.y + unity_WorldToObject[2].xyz * v.normal.z);
					// 世界空间转观察空间
					worldNormal = mul((float3x3)UNITY_MATRIX_V,worldNormal);
					o.matcap.xy = worldNormal.xy * 0.5 + 0.5;
				#endif

				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				// 发线
				fixed3 normalDirection = normalize(i.normalDir);
				// 光照方向
				fixed3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);
				// 观察方向
				fixed3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld);
				// 半角向量
				fixed3 halfDirection = normalize(lightDirection + viewDirection);

				// sample the texture
				fixed4 mainColor = tex2D(_MainTex,i.uv);
				
				// specular
				#if _SPECULAR_ON
					// 高光 = 直射光颜色 * 反射光颜色 * pow(max(0, dot(法线方向,半角向量)), 光泽度(gloss))
					// ndh 0~1 当有两角度之间夹角越小时 值越大
					fixed ndh = max(0,dot(halfDirection,normalDirection)*0.5+0.5);
					fixed specPow = exp2(_Gloss * 10. + 1.0);	// 高光范围 值越大越小 pow(ndh,specPow)
					fixed3 specularColor = _SpecularColor.rgb;  // 高光颜色
					fixed3 directSpecular = attenColor * pow(ndh,specPow) * specularColor;
				#else
					fixed3 directSpecular = fixed3(0,0,0);
				#endif

				//matcap高光
				#if _REFLECT_ON
				half maskMap = tex2D(_MatCap,i.uv).r;
					fixed3 specularAO = _SpecularAO;  // 颜色强度
					// 返回 matcap 上的明暗颜色显示
					fixed3 indirectSpecular = tex2D(_MatCap,i.matcap).rgb * _specularAO;
					// 角色高光
					#if _SPECULAR_ON
						// 相当于 高光强度*高光颜色
						indirectSpecular *= specularColor;
					#endif
				#else
					fixed3 indirectSpecular = fixed3(0,0,0);
				#endif

				// 最终高光颜色( 普通高光 + matcap高光)
				float3 specular = (directSpecular + indirectSpecular) * _SpecularIntensity;

				fixed3 finalColor = mainColor.rgb + specular.rgb;

				UNITY_APPLY_FOG(i.fogCoord, mainColor);
				return fixed4(finalColor,1);
				//return i.uv.x;
			}
			ENDCG
		}
	}
}
